package com.linzelin.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.linzelin.config.RsaKeyProperties;
import com.linzelin.pojo.Payload;
import com.linzelin.pojo.SysUser;
import com.linzelin.utils.JwtUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录校验用拦截器
 */
public class JwtVerityFilter extends BasicAuthenticationFilter {


    private RsaKeyProperties prop;

    /**
     * 构造注入方法`
     */
    public JwtVerityFilter(AuthenticationManager authenticationManager, RsaKeyProperties prop) {
        super(authenticationManager);
        this.prop = prop;
        //注意这里是需要通过构造函数的方式来注入这个RsaKeyProperties的
    }

    /**
     * 注意这里的方法前缀要改为public
     */
    @Override
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String header = request.getHeader("Authorization");
        if (header == null || !header.startsWith("Bearer ")) {
            chain.doFilter(request, response);
            //这个就是从服务器获取令牌后的校验工作了
            //如果没有对应的header对象或是携带的头不是我们指定的头的话
            //就不能登录,就给用户发送提示叫他登录
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            PrintWriter writer = response.getWriter();
            Map resultMap = new HashMap();
            resultMap.put("code", HttpServletResponse.SC_FORBIDDEN);
            resultMap.put("msg", "请登录");
            writer.write(new ObjectMapper().writeValueAsString(resultMap));
            //将认证成功的通知发送一下
            writer.flush();
            writer.close();

        } else {
            //如果携带的是正确格式的token就需要验证一下了
            String token = header.replace("Bearer ", "");
            //将token对应的前缀转化为空字符串

            /*验证token是否正确*/
            Payload<SysUser> payload = JwtUtils.getInfoFromToken(token, prop.getPublicKey(), SysUser.class);
            //这里因为是解析,所以要使用公钥来解析,解析完成后转为我们自定义的那个载荷封装类
            SysUser user = payload.getUserInfo();
            if (user != null) {
                UsernamePasswordAuthenticationToken authResult = new UsernamePasswordAuthenticationToken(user.getUsername(), null, user.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authResult);
                chain.doFilter(request, response);
            }
        }

        super.doFilterInternal(request, response, chain);
    }
}
